#!/bin/bash

# 环境检测模块 / Environment Detection Module
# 提供跨平台的系统环境检测和兼容性验证功能

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 全局变量
DETECTED_OS=""
DETECTED_OS_VERSION=""
DETECTED_ARCHITECTURE=""
SYSTEM_RESOURCES=()
NETWORK_STATUS=()

# 函数：检测操作系统
detect_os() {
    if [[ -f /etc/os-release ]]; then
        source /etc/os-release
        case $ID in
            ubuntu)
                DETECTED_OS="ubuntu"
                DETECTED_OS_VERSION="$VERSION_ID"
                ;;
            debian)
                DETECTED_OS="debian"
                DETECTED_OS_VERSION="$VERSION_ID"
                ;;
            centos)
                DETECTED_OS="centos"
                DETECTED_OS_VERSION="$VERSION_ID"
                ;;
            rhel)
                DETECTED_OS="rhel"
                DETECTED_OS_VERSION="$VERSION_ID"
                ;;
            fedora)
                DETECTED_OS="fedora"
                DETECTED_OS_VERSION="$VERSION_ID"
                ;;
            *)
                DETECTED_OS="unknown"
                DETECTED_OS_VERSION="unknown"
                ;;
        esac
    elif [[ -f /etc/redhat-release ]]; then
        if grep -q "CentOS" /etc/redhat-release; then
            DETECTED_OS="centos"
            DETECTED_OS_VERSION=$(grep -oE '[0-9]+\.[0-9]+' /etc/redhat-release | head -1)
        elif grep -q "Red Hat" /etc/redhat-release; then
            DETECTED_OS="rhel"
            DETECTED_OS_VERSION=$(grep -oE '[0-9]+\.[0-9]+' /etc/redhat-release | head -1)
        fi
    elif [[ -f /etc/debian_version ]]; then
        DETECTED_OS="debian"
        DETECTED_OS_VERSION=$(cat /etc/debian_version)
    else
        DETECTED_OS="unknown"
        DETECTED_OS_VERSION="unknown"
    fi
    
    echo "$DETECTED_OS"
}

# 函数：检测系统架构
detect_architecture() {
    DETECTED_ARCHITECTURE=$(uname -m)
    case $DETECTED_ARCHITECTURE in
        x86_64)
            echo "x86_64"
            ;;
        aarch64|arm64)
            echo "arm64"
            ;;
        armv7l)
            echo "armv7"
            ;;
        *)
            echo "$DETECTED_ARCHITECTURE"
            ;;
    esac
}

# 函数：检查系统资源
check_system_resources() {
    local cpu_cores=$(nproc)
    local memory_gb=$(free -g | awk '/^Mem:/{print $2}')
    local memory_mb=$(free -m | awk '/^Mem:/{print $2}')
    local disk_total_gb=$(df -BG / | awk 'NR==2{print $2}' | sed 's/G//')
    local disk_available_gb=$(df -BG / | awk 'NR==2{print $4}' | sed 's/G//')
    
    # 如果内存显示为0GB，使用MB计算
    if [[ $memory_gb -eq 0 ]]; then
        memory_gb=$(echo "scale=1; $memory_mb/1024" | bc -l)
    fi
    
    SYSTEM_RESOURCES=(
        "cpu_cores:$cpu_cores"
        "memory_gb:$memory_gb"
        "memory_mb:$memory_mb"
        "disk_total_gb:$disk_total_gb"
        "disk_available_gb:$disk_available_gb"
    )
    
    # 返回资源状态
    echo "CPU核心数: $cpu_cores"
    echo "内存: ${memory_gb}GB (${memory_mb}MB)"
    echo "磁盘总空间: ${disk_total_gb}GB"
    echo "磁盘可用空间: ${disk_available_gb}GB"
}

# 函数：检查网络连接
check_network_connectivity() {
    local connectivity_status="good"
    local dns_status="good"
    local proxy_required="false"
    local internet_access="true"
    
    # 检查基本网络连接
    if ! ping -c 1 -W 5 8.8.8.8 >/dev/null 2>&1; then
        if ! ping -c 1 -W 5 114.114.114.114 >/dev/null 2>&1; then
            connectivity_status="poor"
            internet_access="false"
        fi
    fi
    
    # 检查DNS解析
    if ! nslookup google.com >/dev/null 2>&1; then
        if ! nslookup baidu.com >/dev/null 2>&1; then
            dns_status="poor"
        fi
    fi
    
    # 检查是否需要代理
    if [[ -n "$http_proxy" ]] || [[ -n "$HTTP_PROXY" ]]; then
        proxy_required="true"
    fi
    
    NETWORK_STATUS=(
        "connectivity:$connectivity_status"
        "dns:$dns_status"
        "proxy_required:$proxy_required"
        "internet_access:$internet_access"
    )
    
    echo "网络连接: $connectivity_status"
    echo "DNS解析: $dns_status"
    echo "代理设置: $proxy_required"
    echo "互联网访问: $internet_access"
}

# 函数：检测已安装的服务
detect_existing_services() {
    local services=("nginx" "apache2" "httpd" "mysql" "mysqld" "mariadb" "postgresql" "node" "pm2")
    local installed_services=()
    
    for service in "${services[@]}"; do
        if command -v "$service" >/dev/null 2>&1; then
            local version=""
            case $service in
                nginx)
                    version=$(nginx -v 2>&1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')
                    ;;
                mysql|mysqld)
                    version=$(mysql --version 2>/dev/null | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
                    ;;
                node)
                    version=$(node --version 2>/dev/null | sed 's/v//')
                    ;;
                pm2)
                    version=$(pm2 --version 2>/dev/null)
                    ;;
            esac
            installed_services+=("$service:$version")
        elif systemctl list-unit-files | grep -q "^$service"; then
            installed_services+=("$service:systemd")
        fi
    done
    
    printf '%s\n' "${installed_services[@]}"
}

# 函数：验证最低系统要求
validate_minimum_requirements() {
    local errors=()
    local warnings=()
    
    # 检查CPU核心数（最低1核，推荐2核）
    local cpu_cores=$(nproc)
    if [[ $cpu_cores -lt 1 ]]; then
        errors+=("CPU核心数不足: 需要至少1核，当前: $cpu_cores")
    elif [[ $cpu_cores -lt 2 ]]; then
        warnings+=("CPU核心数较少: 推荐2核或以上，当前: $cpu_cores")
    fi
    
    # 检查内存（最低1GB，推荐2GB）
    local memory_mb=$(free -m | awk '/^Mem:/{print $2}')
    if [[ $memory_mb -lt 1024 ]]; then
        errors+=("内存不足: 需要至少1GB，当前: ${memory_mb}MB")
    elif [[ $memory_mb -lt 2048 ]]; then
        warnings+=("内存较少: 推荐2GB或以上，当前: ${memory_mb}MB")
    fi
    
    # 检查磁盘空间（最低5GB，推荐10GB）
    local disk_available_gb=$(df -BG / | awk 'NR==2{print $4}' | sed 's/G//')
    if [[ $disk_available_gb -lt 5 ]]; then
        errors+=("磁盘空间不足: 需要至少5GB，当前可用: ${disk_available_gb}GB")
    elif [[ $disk_available_gb -lt 10 ]]; then
        warnings+=("磁盘空间较少: 推荐10GB或以上，当前可用: ${disk_available_gb}GB")
    fi
    
    # 检查操作系统支持
    if [[ "$DETECTED_OS" == "unknown" ]]; then
        errors+=("不支持的操作系统: 请使用 Ubuntu、Debian、CentOS 或 RHEL")
    fi
    
    # 输出结果
    if [[ ${#errors[@]} -gt 0 ]]; then
        echo -e "${RED}系统要求验证失败:${NC}"
        printf '%s\n' "${errors[@]}"
        return 1
    fi
    
    if [[ ${#warnings[@]} -gt 0 ]]; then
        echo -e "${YELLOW}系统要求警告:${NC}"
        printf '%s\n' "${warnings[@]}"
    fi
    
    echo -e "${GREEN}系统要求验证通过${NC}"
    return 0
}

# 函数：检测Web服务器用户
detect_web_user() {
    if id "www-data" &>/dev/null; then
        echo "www-data"
    elif id "nginx" &>/dev/null; then
        echo "nginx"
    elif id "apache" &>/dev/null; then
        echo "apache"
    else
        # 根据操作系统返回默认用户
        case "$DETECTED_OS" in
            ubuntu|debian)
                echo "www-data"
                ;;
            centos|rhel|fedora)
                echo "nginx"
                ;;
            *)
                echo "www-data"
                ;;
        esac
    fi
}

# 函数：获取包管理器
get_package_manager() {
    case "$DETECTED_OS" in
        ubuntu|debian)
            echo "apt"
            ;;
        centos|rhel)
            if command -v dnf >/dev/null 2>&1; then
                echo "dnf"
            else
                echo "yum"
            fi
            ;;
        fedora)
            echo "dnf"
            ;;
        *)
            echo "unknown"
            ;;
    esac
}

# 函数：生成环境报告
generate_environment_report() {
    echo "=== 系统环境检测报告 ==="
    echo "操作系统: $DETECTED_OS $DETECTED_OS_VERSION"
    echo "系统架构: $(detect_architecture)"
    echo "包管理器: $(get_package_manager)"
    echo "Web用户: $(detect_web_user)"
    echo
    echo "=== 系统资源 ==="
    check_system_resources
    echo
    echo "=== 网络状态 ==="
    check_network_connectivity
    echo
    echo "=== 已安装服务 ==="
    detect_existing_services
    echo
    echo "=== 系统要求验证 ==="
    validate_minimum_requirements
}

# 函数：保存环境信息到文件
save_environment_info() {
    local output_file="${1:-/tmp/environment-info.json}"
    
    cat > "$output_file" << EOF
{
  "detection_time": "$(date -Iseconds)",
  "os": "$DETECTED_OS",
  "os_version": "$DETECTED_OS_VERSION",
  "architecture": "$(detect_architecture)",
  "package_manager": "$(get_package_manager)",
  "web_user": "$(detect_web_user)",
  "system_resources": {
$(
    for resource in "${SYSTEM_RESOURCES[@]}"; do
        key=$(echo "$resource" | cut -d: -f1)
        value=$(echo "$resource" | cut -d: -f2)
        echo "    \"$key\": \"$value\","
    done | sed '$ s/,$//'
)
  },
  "network_status": {
$(
    for status in "${NETWORK_STATUS[@]}"; do
        key=$(echo "$status" | cut -d: -f1)
        value=$(echo "$status" | cut -d: -f2)
        echo "    \"$key\": \"$value\","
    done | sed '$ s/,$//'
)
  },
  "installed_services": [
$(
    detect_existing_services | while read -r service; do
        echo "    \"$service\","
    done | sed '$ s/,$//'
)
  ]
}
EOF
    
    echo "环境信息已保存到: $output_file"
}

# 主函数：执行完整的环境检测
main() {
    echo "开始环境检测..."
    
    # 执行检测
    detect_os >/dev/null
    check_system_resources >/dev/null
    check_network_connectivity >/dev/null
    
    # 生成报告
    generate_environment_report
    
    # 保存环境信息
    save_environment_info "/tmp/personal-cloud-notes-env.json"
    
    # 返回验证结果
    validate_minimum_requirements
    return $?
}

# 导出函数供其他脚本使用
export -f validate_minimum_requirements
export -f detect_os
export -f detect_web_user
export -f get_package_manager

# 如果直接运行此脚本
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi